/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.basic.drive.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.basic.common.constant.FlowDicConstant;
import com.hopes.bizz.basic.common.constant.FlowConstant;
import com.hopes.bizz.basic.common.constant.enums.ParkBasicSysDictEnum;
import com.hopes.bizz.basic.drive.bo.BaseTaskBo;
import com.hopes.bizz.basic.drive.dto.BaseAuditDTO;
import com.hopes.bizz.basic.drive.dto.BaseDriveStopRecordExcelDTO;
import com.hopes.bizz.basic.drive.entity.BaseDriveStopHandleRecordEntity;
import com.hopes.bizz.basic.drive.entity.BaseDriveStopRecordEntity;
import com.hopes.bizz.basic.drive.mapper.BaseDriveStopRecordMapper;
import com.hopes.bizz.basic.drive.service.BaseDriveStopHandleRecordService;
import com.hopes.bizz.basic.drive.service.BaseDriveStopRecordService;
import com.hopes.bizz.basic.drive.vo.BaseDriveStopRecordExcelVO;
import com.hopes.bizz.basic.gis.vo.DriveStopRecordVo;
import com.hopes.bizz.common.core.validate.ValidatorUtils;
import com.hopes.boss.act.base.FlowServiceImpl;
import com.hopes.boss.act.base.TaskExecute;
import com.hopes.boss.act.enums.FlowTaskHandlerType;
import com.hopes.boss.act.vo.FlowTaskInfo;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import com.hopes.boss.common.entity.ValidateImportBO;
import com.hopes.boss.common.excel.vo.ErrorMessage;
import com.hopes.boss.common.security.util.SecurityUtils;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 开停车申报
 *
 * @author pig
 * @date 2023-11-02 09:27:34
 */
@Service
@Slf4j
public class BaseDriveStopRecordServiceImpl extends FlowServiceImpl<BaseDriveStopRecordMapper, BaseDriveStopRecordEntity> implements BaseDriveStopRecordService {

    @Autowired
    private BaseDriveStopHandleRecordService baseDriveStopHandleRecordService;

    @Override
    public ValidateImportBO<BaseDriveStopRecordExcelDTO> validateImport(List<BaseDriveStopRecordExcelDTO> excelDTOList) {
        ValidateImportBO<BaseDriveStopRecordExcelDTO> bo = new ValidateImportBO<>();
        List<ErrorMessage> errorMessageList = new ArrayList<>();
        List<BaseDriveStopRecordExcelDTO> saveList = new ArrayList<>();
        int successNum = 0;
        int failedNum = 0;
        for (BaseDriveStopRecordExcelDTO baseDriveStopRecordExcelDTO : excelDTOList) {
            String validateRes = ValidatorUtils.validateEntity(baseDriveStopRecordExcelDTO);
            if (StrUtil.isEmpty(validateRes)) {
                successNum++;
                saveList.add(baseDriveStopRecordExcelDTO);
            } else {
                failedNum++;
                errorMessageList.add(new ErrorMessage(baseDriveStopRecordExcelDTO.getLineNum(), new HashSet<String>() {{
                    add(validateRes);
                }}));
            }
        }
        bo.setErrorMessages(errorMessageList);
        bo.setSaveList(saveList);
        bo.setSuccessNum(successNum);
        bo.setFailedNum(failedNum);
        return bo;
    }

    @Override
    public BaseDriveStopRecordEntity importDtoToEntity(BaseDriveStopRecordExcelDTO excelDto) {
        BaseDriveStopRecordEntity entity = new BaseDriveStopRecordEntity();
        BeanUtils.copyProperties(excelDto, entity);
        entity.setOrgId(Long.valueOf(DictResolver.getItemValueByLabel(AdminDictEnum.sys_company, excelDto.getOrgId())));
        entity.setRecordType(DictResolver.getItemValueByLabel(ParkBasicSysDictEnum.drive_record_type, excelDto.getRecordType()));
        return entity;
    }

    @Override
    public BaseDriveStopRecordExcelVO exportEntityToVo(BaseDriveStopRecordEntity entity) {
        BaseDriveStopRecordExcelVO excelVO = new BaseDriveStopRecordExcelVO();
        BeanUtils.copyProperties(entity, excelVO);
        return excelVO;
    }

    @Override
    public DriveStopRecordVo getDriveStopRecord() {
        DriveStopRecordVo driveStopRecordVo = new DriveStopRecordVo();
        JSONArray pieData = new JSONArray();
        JSONObject barData = new JSONObject();
        List<BaseDriveStopRecordEntity> stopRecordEntities = baseMapper.selectList(null);
        // 状态统计
        Map<String, Long> statusMap = stopRecordEntities.stream().collect(Collectors.groupingBy(BaseDriveStopRecordEntity::getRecordStatus, Collectors.counting()));
        statusMap.forEach((k, v) -> {
            JSONObject data = new JSONObject();
            data.put("name", DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.audit_status, k));
            data.put("value", v);

            pieData.add(data);
        });
        // 类型统计
        Map<String, Long> typeMap = stopRecordEntities.stream().collect(Collectors.groupingBy(BaseDriveStopRecordEntity::getRecordType, Collectors.counting()));
        ArrayList<String> name = new ArrayList<>();
        barData.put("name", name);
        ArrayList<Long> count = new ArrayList<>();
        barData.put("count", count);
        typeMap.forEach((k, v) -> {
            name.add(DictResolver.getItemLabelByValue(ParkBasicSysDictEnum.drive_record_type, k));
            count.add(v);
        });
        driveStopRecordVo.setPieData(pieData);
        driveStopRecordVo.setBarData(barData);
        return driveStopRecordVo;
    }


    @Override
    @GlobalTransactional // 分布式事务注解
    public void handlerAudit(BaseAuditDTO baseAuditDTO) {
        Long id = baseAuditDTO.getId();
        FlowTaskHandlerType flowTaskHandlerType = FlowTaskHandlerType.getFlowTaskHandlerTypeByCode(baseAuditDTO.getHandleResult());
        // 提交工作流
        BaseTaskBo baseTaskBo = new BaseTaskBo()
                .setHandleResultDesc(baseAuditDTO.getHandleResultDesc())
                .setAttachment(baseAuditDTO.getAttachment())
                .setHandleTime(baseAuditDTO.getHandleTime())
                .setSignature(baseAuditDTO.getSignature());
        TaskExecute taskExecute = new TaskExecute.Build()
                .setBusinessKey(id)
                .setFlowTaskHandlerType(flowTaskHandlerType)
                .setBusinessData(baseTaskBo)
                .build();
        executeTask(taskExecute);
    }

    @Override
    @GlobalTransactional // 分布式事务注解
    public void handleDriveSubmit(Long id) {
        TaskExecute taskExecute = new TaskExecute.Build()
                .setBusinessKey(id)
                .setFlowTaskHandlerType(FlowTaskHandlerType.TASK_HANDLE_TYPE_SUBMIT)
                .build();
        executeTask(taskExecute);
    }


    @Override
    public void doCompletedTask(FlowTaskInfo flowTaskInfo, Long id, FlowTaskHandlerType handlerType, Object data) {
        // 提交操作创建当前节点和下一节点
        if (FlowTaskHandlerType.TASK_HANDLE_TYPE_SUBMIT.equals(handlerType)) {
            BaseDriveStopHandleRecordEntity startNode = new BaseDriveStopHandleRecordEntity();
            startNode.setNodeCode(FlowDicConstant.START);
            startNode.setBusinessId(id);
            startNode.setHandleUserId(SecurityUtils.getUserId());
            startNode.setHandleTime(new Date());
            baseDriveStopHandleRecordService.save(startNode);
            // 下一节点
            BaseDriveStopHandleRecordEntity nextNode = new BaseDriveStopHandleRecordEntity();
            nextNode.setNodeCode(flowTaskInfo.getStatus());
            nextNode.setBusinessId(id);
            nextNode.setExecutor(flowTaskInfo.getCandidateStr());
            baseDriveStopHandleRecordService.save(nextNode);
            // 更新当前纪录为填报中
            lambdaUpdate().set(BaseDriveStopRecordEntity::getRecordStatus, FlowDicConstant.IN_REVIEW)
                    .eq(BaseDriveStopRecordEntity::getId, id).update();
        } else {
            BaseTaskBo baseTaskBo = (BaseTaskBo) data;
            // 通过 更新上一节点
            BaseDriveStopRecordEntity driveStopRecordEntity = getById(id);
            BaseDriveStopHandleRecordEntity preRecord = baseDriveStopHandleRecordService.lambdaQuery()
                    .eq(BaseDriveStopHandleRecordEntity::getBusinessId, id)
                    .eq(BaseDriveStopHandleRecordEntity::getNodeCode, driveStopRecordEntity.getRecordStatus())
                    .orderByDesc(BaseDriveStopHandleRecordEntity::getCreateTime)
                    .select(BaseDriveStopHandleRecordEntity::getId)
                    .last("limit 1")
                    .one();
            baseDriveStopHandleRecordService.lambdaUpdate()
                    .eq(BaseDriveStopHandleRecordEntity::getId, preRecord.getId())
                    .set(BaseDriveStopHandleRecordEntity::getHandleUserId, SecurityUtils.getUserId())
                    .set(BaseDriveStopHandleRecordEntity::getHandleResultDesc, baseTaskBo.getHandleResultDesc())
                    .set(BaseDriveStopHandleRecordEntity::getHandleTime, baseTaskBo.getHandleTime())
                    .set(BaseDriveStopHandleRecordEntity::getAttachment, baseTaskBo.getAttachment())
                    .set(BaseDriveStopHandleRecordEntity::getSignature, baseTaskBo.getSignature())
                    .set(BaseDriveStopHandleRecordEntity::getHandleResult, handlerType.getName())
                    .update();
        }
        if (FlowTaskHandlerType.TASK_HANDLE_TYPE_PASS.equals(handlerType)) {
            // 更新当前纪录为审核通过
            lambdaUpdate().set(BaseDriveStopRecordEntity::getRecordStatus, FlowDicConstant.PASS)
                    .eq(BaseDriveStopRecordEntity::getId, id).update();
        } else if (FlowTaskHandlerType.TASK_HANDLE_TYPE_BACK.equals(handlerType)) {
            // 更新当前纪录为审核通过
            lambdaUpdate().set(BaseDriveStopRecordEntity::getRecordStatus, FlowDicConstant.NOT_PASS)
                    .eq(BaseDriveStopRecordEntity::getId, id).update();
        }
    }


    @Override
    public void deleteBusiness(Collection<Long> driveList) {
        // 删除相关处理纪录
        baseDriveStopHandleRecordService.remove(Wrappers.lambdaQuery(BaseDriveStopHandleRecordEntity.class).in(BaseDriveStopHandleRecordEntity::getBusinessId, driveList));
    }

    @Override
    public String getFlowDefinitionKey(Long id) {
        return FlowConstant.BASE_DRIVE_STOP_RECORD;
    }
}
